﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;

namespace rePose
{
        [StructLayout(LayoutKind.Sequential, Size = 4)]
        public struct HDC__
        {
        }
        [StructLayout(LayoutKind.Sequential, Size = 4)]
        public struct HWND__
        {
        }
        [StructLayout(LayoutKind.Sequential, Size = 8)]
        public struct tagSIZE
        {
            public int cx;
            public int cy;
        }
        [StructLayout(LayoutKind.Sequential, Size = 0x10)]
        public struct tagRECT
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
        [StructLayout(LayoutKind.Sequential, Size = 4)]
        public struct HBITMAP__
        {
        }

    class WinAPI
    {
        // For Windows Mobile, replace user32.dll with coredll.dll
        [DllImport("user32.dll")]
    
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        [DllImport("kernel32.dll")]
        static extern unsafe HDC__* GetDC(HWND__* j);

        [DllImport("user32.dll")]
        static extern unsafe HDC__* GetWindowDC(HWND__* g);

        [DllImport("gdi32.dll")]
        static extern unsafe HDC__* CreateCompatibleDC(HDC__* g);

        [DllImport("user32.dll")]
        static extern unsafe int GetWindowRect(HWND__* u, tagRECT* g);

        [DllImport("user32.dll")]
        static extern unsafe int GetClientRect(HWND__* u, tagRECT* g);

        [DllImport("gdi32.dll")]
        static extern unsafe HBITMAP__* CreateCompatibleBitmap(HDC__* c, int h, int r);

        [DllImport("gdi32.dll")]
        static extern unsafe void* SelectObject(HDC__* e, void* s);

        [DllImport("gdi32.dll")]
        static extern unsafe int BitBlt(HDC__* a1, int a2, int a3, int a4, int a5, HDC__* a6, int a8, int a9, uint a10);

        [DllImport("gdi32.dll")]
        static extern unsafe int DeleteDC(HDC__* vf);

        [DllImport("user32.dll")]
        static extern unsafe int ReleaseDC(HWND__* g, HDC__* m);

        [DllImport("gdi32.dll")]
        static extern unsafe int DeleteObject(void* g);

        delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
        [DllImport("user32.dll")]
        static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

        [DllImport("user32.dll")]
        static extern bool IsWindowVisible(IntPtr hWnd);


        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern int GetWindowTextLength(IntPtr hWnd);
        public enum SHOWWINDOW : uint
        {
            SW_HIDE = 0,
            SW_SHOWNORMAL = 1,
            SW_NORMAL = 1,
            SW_SHOWMINIMIZED = 2,
            SW_SHOWMAXIMIZED = 3,
            SW_MAXIMIZE = 3,
            SW_SHOWNOACTIVATE = 4,
            SW_SHOW = 5,
            SW_MINIMIZE = 6,
            SW_SHOWMINNOACTIVE = 7,
            SW_SHOWNA = 8,
            SW_RESTORE = 9,
            SW_SHOWDEFAULT = 10,
            SW_FORCEMINIMIZE = 11,
            SW_MAX = 11,
        }

        [DllImport("user32.dll")]
        static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        static bool EnumThreadCallback(IntPtr hWnd, IntPtr lParam)
        {
            if (IsWindowVisible(hWnd))
            {
                GCHandle gch = GCHandle.FromIntPtr(lParam);
                List<IntPtr> list = gch.Target as List<IntPtr>;
                if (list == null)
                {
                    throw new InvalidCastException
                    ("GCHandle Target could not be cast as List");
                }
                if(GetWindowTitle(hWnd)!="")
                list.Add(hWnd);
            }
            return true;
        }

        public static unsafe Rectangle GetWindowRectangle(IntPtr hWnd)
        {
            tagRECT r;
            GetWindowRect((HWND__*)hWnd.ToInt32(), &r);
            Rectangle ret = new Rectangle(r.left, r.top, r.right, r.bottom);
            return ret;
        }

        public static string GetWindowTitle(IntPtr hWnd)
        {
            // Allocate correct string length first
            int length = GetWindowTextLength(hWnd);
            StringBuilder sb = new StringBuilder(length + 1);
            GetWindowText(hWnd, sb, sb.Capacity);
            return sb.ToString();
        }

        public static List<IntPtr> getVisibleWindows()
        {
            List<IntPtr> _windowHandles = new List<IntPtr>();
            GCHandle listHandle = GCHandle.Alloc(_windowHandles);
            try
            {
                EnumWindows(new EnumWindowsProc(EnumThreadCallback), GCHandle.ToIntPtr(listHandle));
            }
            finally
            {
                if (listHandle != default(GCHandle) && listHandle.IsAllocated)
                    listHandle.Free();
            }
            return _windowHandles;
        }

        public static  unsafe Image CaptureWindow(IntPtr hWnd)
        {
            HDC__* hDC;
            tagSIZE size;
            tagRECT r;
            Image im = null;
            ShowWindow(hWnd, (int)SHOWWINDOW.SW_SHOW);
            hDC = GetWindowDC(((HWND__*)hWnd.ToInt32()));
            
            HDC__* hMemDC = CreateCompatibleDC(hDC);
            GetWindowRect((HWND__*)hWnd.ToInt32(), &r);
            size.cx = r.right - r.left;
            size.cy = r.bottom - r.top;
            HBITMAP__* hBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);
            if (hBitmap != null)
            {
                HBITMAP__* hOld = (HBITMAP__*)SelectObject(hMemDC, (void*)hBitmap);
                BitBlt(hMemDC, 0, 0, size.cx, size.cy, hDC, 0, 0, 0xcc0020);
                SelectObject(hMemDC, (void*)hOld);
                DeleteDC(hMemDC);
                ReleaseDC(null, hDC);
                IntPtr hbitmap = new IntPtr((void*)hBitmap);
                im = Image.FromHbitmap(hbitmap);
                DeleteObject((void*)hBitmap);
            }
            return im;
        }


    }
}
